iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0
自我挑戰組

跟 AI Agent 變成好朋友系列 第 23

【Day23】AI Agent 魔法詠唱 - MoodDetection Service

  • 分享至 

  • xImage
  •  

MoodDetectionService,主要根據使用者輸入的文字,自動偵測並判斷心情。用於聊天室,讓系統能根據使用者的心情給予更貼近需求的回應或建議。

核心功能說明:

  1. 關鍵字比對

    服務初始化時,依照已定義的心情相關的關鍵字,例如「開心」、「放鬆」、「疲憊」、「專注」等,以及英文對應詞(如 happy, relaxed, tired),將使用者的輸入分割成詞語,然後逐一比對每個 mood 的關鍵字,並根據關鍵字長度加分。系統會先將內容轉為小寫,並根據偵測到的關鍵字,判定對應的心情。若有多個心情被偵測,取分數最高者,並依分數計算信心度。

    private final Map<String, Set<String>> moodKeywords = initializeMoodKeywords();
    
    private String getMoodDescription(String mood) {
        switch (mood) {
            case "happy": return "開心愉快";
            case "relaxed": return "放鬆平靜";
            case "tired": return "疲憊想休息";
            case "energetic": return "充滿活力";
            case "stressed": return "有壓力焦慮";
            case "sad": return "傷心沮喪";
            case "romantic": return "浪漫溫馨";
            case "focused": return "專注工作";
            case "refreshed": return "需要清爽";
            case "cozy": return "溫暖舒適";
            default: return "中性心情";
        }
    }
    
    private Map<String, Set<String>> initializeMoodKeywords() {
        Map<String, Set<String>> keywords = new HashMap<>();
    
        // 開心/興奮
        keywords.put("happy", new HashSet<>(Arrays.asList(
            "開心", "高興", "快樂", "興奮", "激動", "愉快", "喜悅", "歡樂",
            "happy", "excited", "joyful", "cheerful", "delighted", "elated"
        )));
    
        // 放鬆/平靜
        keywords.put("relaxed", new HashSet<>(Arrays.asList(
            "放鬆", "平靜", "安靜", "冷靜", "舒服", "悠閒", "輕鬆", "寧靜",
            "relaxed", "calm", "peaceful", "tranquil", "serene", "zen"
        )));
    
        // 疲憊/累
        keywords.put("tired", new HashSet<>(Arrays.asList(
            "累", "疲憊", "疲勞", "困", "想睡", "無力", "倦", "乏",
            "tired", "exhausted", "weary", "sleepy", "drained", "fatigue"
        )));
    
        // 有活力/精神
        keywords.put("energetic", new HashSet<>(Arrays.asList(
            "有活力", "精神", "充滿活力", "有精神", "清醒", "振奮", "活躍",
            "energetic", "vigorous", "lively", "active", "alert", "refreshed"
        )));
    
        // 壓力/焦慮
        keywords.put("stressed", new HashSet<>(Arrays.asList(
            "壓力", "焦慮", "緊張", "煩躁", "不安", "憂心", "緊迫", "煩惱",
            "stressed", "anxious", "worried", "nervous", "tense", "overwhelmed"
        )));
    
        // 悲傷/沮喪
        keywords.put("sad", new HashSet<>(Arrays.asList(
            "傷心", "難過", "沮喪", "憂鬱", "低落", "失望", "鬱悶", "悲傷",
            "sad", "depressed", "down", "disappointed", "melancholy", "blue"
        )));
    
        // 浪漫/溫馨
        keywords.put("romantic", new HashSet<>(Arrays.asList(
            "浪漫", "甜蜜", "溫馨", "約會", "情人", "戀愛", "愛情",
            "romantic", "warm", "sweet", "intimate", "loving"
            // "cozy" 已移除,避免與 cozy mood 混淆
        )));
    
        // 專注/工作
        keywords.put("focused", new HashSet<>(Arrays.asList(
            "專注", "工作", "學習", "讀書", "思考", "集中", "努力", "認真",
            "focused", "concentrated", "studying", "working", "productive"
        )));
    
        // 清爽/提神
        keywords.put("refreshed", new HashSet<>(Arrays.asList(
            "清爽", "提神", "refresh", "refreshed", "醒腦", "涼快", "cool", "fresh"
        )));
    
        // 溫暖/舒適
        keywords.put("cozy", new HashSet<>(Arrays.asList(
            "溫暖", "舒適", "cozy", "暖和", "暖", "comfortable", "snug"
        )));
    
        return keywords;
    }
    
    public MoodDetectionResult detectMood(String input) {
        if (input == null || input.trim().isEmpty()) {
            return new MoodDetectionResult("neutral", "無特定心情", 0.0);
        }
    
        String lowerInput = input.toLowerCase();
        Map<String, Integer> moodScores = new HashMap<>();
    
        // 以空白、標點分割詞語
        String[] words = lowerInput.split("[\\s\\p{Punct}]+");
        Set<String> wordSet = new HashSet<>(Arrays.asList(words));
    
        // 計算每種心情的匹配分數(完整詞語比對)
        for (Map.Entry<String, Set<String>> entry : moodKeywords.entrySet()) {
            String mood = entry.getKey();
            Set<String> keywords = entry.getValue();
    
            int score = 0;
            for (String keyword : keywords) {
                String lowerKeyword = keyword.toLowerCase();
                // 完整詞語比對
                if (wordSet.contains(lowerKeyword)) {
                    score += lowerKeyword.length(); // 較長的關鍵字有更高的權重
                }
            }
    
            if (score > 0) {
                moodScores.put(mood, score);
            }
        }
    
        // 找出最高分的心情
        if (moodScores.isEmpty()) {
            return detectMoodFromContext(input);
        }
    
        String detectedMood = Collections.max(moodScores.entrySet(), 
                                            Map.Entry.comparingByValue()).getKey();
        int maxScore = moodScores.get(detectedMood);
        double confidence = Math.min(maxScore / 10.0, 1.0); // 信心度標準化為 0-1
    
      return new MoodDetectionResult(detectedMood, getMoodDescription(detectedMood), confidence);
    }
    
  2. 情境推測

    除了直接比對的心情關鍵字,MoodDetectionService 也能透過分析輸入中的時間(早上、晚上)、天氣(炎熱、寒冷)等。這些情境詞彙有助於推測使用者可能的心情,例如「寒冷的天氣很適合喝熱茶放鬆」,系統可判斷「放鬆」為主要心情。讓系統在沒有明確心情關鍵字時,依據情境詞彙判斷最可能的心情。

    private MoodDetectionResult detectMoodFromContext(String input) {
        String lowerInput = input.toLowerCase();
    
        // 時間相關的心情推測
        if (lowerInput.contains("早上") || lowerInput.contains("morning")) {
            return new MoodDetectionResult("energetic", "早晨需要活力", 0.6);
        }
        if (lowerInput.contains("下午") || lowerInput.contains("afternoon")) {
            return new MoodDetectionResult("focused", "下午工作時光", 0.5);
        }
        if (lowerInput.contains("晚上") || lowerInput.contains("evening") || 
            lowerInput.contains("夜晚") || lowerInput.contains("night")) {
            return new MoodDetectionResult("relaxed", "夜晚放鬆時刻", 0.6);
        }
    
        // 天氣相關的心情推測
        if (lowerInput.contains("熱") || lowerInput.contains("夏天") || lowerInput.contains("hot")) {
            return new MoodDetectionResult("refreshed", "炎熱天氣", 0.5);
        }
        if (lowerInput.contains("冷") || lowerInput.contains("冬天") || lowerInput.contains("cold")) {
            return new MoodDetectionResult("cozy", "寒冷天氣", 0.5);
        }
    
        // 默認中性心情
        return new MoodDetectionResult("neutral", "中性心情", 0.3);
    }
    
  3. 回傳心情類型、描述與信心度

    最終,當偵測到心情後,MoodDetectionService 會回傳一個結果物件,內容包含:

  • 心情類型 mood(如「relaxed」、「tired」)

    • 心情描述 description(如「夜晚放鬆時刻」、「疲憊想休息」)
    • 信心度 confidence score,以 0~1 的小數點形式表示 ,並限制最大值為 1.0,確保信心度介於 0 到 1 之間,並以小數點表示。
    public static class MoodDetectionResult {
        private final String mood;
        private final String description;
        private final double confidence;
    
        public MoodDetectionResult(String mood, String description, double confidence) {
            this.mood = mood;
            this.description = description;
            this.confidence = confidence;
        }
    
        public String getMood() { return mood; }
        public String getDescription() { return description; }
        public double getConfidence() { return confidence; }
    }
    

運作流程:

  1. 使用者輸入:「今天工作很累,想喝杯咖啡提神。」
  2. 系統比對到「累」→ tired,並偵測到「工作」情境。
  3. 回傳結果:心情類型「tired」,描述「工作後感到疲憊,建議喝提神飲品」,信心度 0.9。

總結來說,MoodDetectionService 讓系統能根據使用者輸入內容,回傳心情類型(mood)、心情描述(description)以及信心度(confidence),使推薦更符合使用者當下情緒,進一步提升互動體驗與推薦的準確度。


參考資料:

  1. feelings - Vocabulary List _ Vocabulary.com
  2. 情緒量表 - Character Lab _ Positive Education Hong Kong
  3. 情緒儀表

上一篇
【Day22】AI Agent 魔法詠唱 - ContentFilter Service
下一篇
【Day24】AI Agent 魔法詠唱 - BedrockAI Service
系列文
跟 AI Agent 變成好朋友25
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言